﻿using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace YuYuKiCms.Framework.UnitTest
{
    /// <summary>
    /// 	<para>Cette class est un Assert Helper</para>
    /// 	<para>Chacune de ses méthodes est destinée à faciliter les testes</para>
    /// </summary>
    public static class PropertyAssert
    {
        /// <summary>
        /// 	<para>Cette méthode vérifie si 2 objets de même type ont des propriétés de même
        /// valeur. </para>
        /// 	<para>Si ce n'est pas le cas, un Assert est lancé sur la propriété dont la
        /// valeur est différente.</para>
        /// </summary>
        /// <remarks>
        /// Cette fonction ne vérifie pas les propriétés de manière récurcive
        /// </remarks>
        /// <typeparam name="T"></typeparam>
        /// <param name="expectedOb">Required.</param>
        /// <param name="actualOb">Required.</param>
        /// <param name="propertyNotIncludes">Optional. The default value is null.</param>
        public static void ArePropertyEqual<T>(T expectedOb, T actualOb, string[] propertyNotIncludes = null)
            where T : class
        {
            Assert.IsTrue(expectedOb != null, "l'objet de référence est null");
            Assert.IsTrue(actualOb != null, "l'objet de résultat est null");

            var type = expectedOb.GetType();

            propertyNotIncludes = propertyNotIncludes ?? new string[] { };

            type.GetProperties()
                .Select(f => f.Name)
                .Except(propertyNotIncludes)
                .ToList()
                .ForEach(p =>
                {
                    var expected = Convert.ToString(type.GetProperty(p).GetValue(expectedOb));
                    var actual = Convert.ToString(type.GetProperty(p).GetValue(actualOb));
                    var resultat = expected == actual;
                    Assert.IsTrue(resultat, "The value of property " + p + " is not equal.");
                });
        }

        public static void ArePropertyEqual<TSource, TDestination>(TSource expectedOb, TDestination actualOb)
            where TSource : class
            where TDestination : class
        {
            Assert.IsTrue(expectedOb != null, "l'objet de référence est null");
            Assert.IsTrue(actualOb != null, "l'objet de résultat est null");

            var typeT = expectedOb.GetType();
            var typeK = actualOb.GetType();

            var properties = typeK.GetProperties().Select(f => f.Name);

            typeT.GetProperties()
                .Select(f => f.Name)
                .ToList()
                .ForEach(p =>
                {
                    if (properties.Contains(p))
                    {
                        var expected = Convert.ToString(typeT.GetProperty(p).GetValue(expectedOb));
                        var actual = Convert.ToString(typeK.GetProperty(p).GetValue(actualOb));
                        var resultat = expected == actual;
                        Assert.IsTrue(resultat, "The value of property " + p + " is not equal.");
                    }
                });
        }
    }
}